home *** CD-ROM | disk | FTP | other *** search
- /* ICMP-related user commands */
- #include <stdio.h>
- #include "global.h"
- #include "icmp.h"
- #include "mbuf.h"
- #include "netuser.h"
- #include "internet.h"
- #include "timer.h"
- #include "ping.h"
-
- extern char nospace[];
- extern char badhost[];
-
- int
- doicmpstat()
- {
- extern struct icmp_errors icmp_errors;
- extern struct icmp_stats icmp_stats;
- extern char *icmptypes[];
- register int i;
-
- printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
- icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
- icmp_errors.bdcsts);
- printf("type rcvd sent\n");
- for(i=0;i<ICMP_TYPES;i++){
- if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
- continue;
- printf("%-6u%-6u%-6u",i,icmp_stats.input[i],
- icmp_stats.output[i]);
- if(icmptypes[i] != NULLCHAR)
- printf(" %s",icmptypes[i]);
- printf("\n");
- }
- return 0;
- }
-
- /* Hash table list heads */
- struct ping *ping[PMOD];
-
- /* Length of ping packets (default to 0) */
- static int16 pinglen;
-
- /* Counter for generating seq numbers */
- static int16 iclk;
-
- /* Increment counter -- called by low level clock tick */
- icmpclk()
- {
- iclk++;
- }
-
- /* Send ICMP Echo Request packets */
- doping(argc,argv)
- int argc;
- char *argv[];
- {
- int32 dest;
- struct ping *add_ping(),*pp1;
- register struct ping *pp;
- void ptimeout();
- int16 hval,hash_ping();
- int i;
-
- if(argc < 2){
- printf("Host Sent Rcvd %% Avg RTT Interval Length\n");
- for(i=0;i<PMOD;i++){
- for(pp = ping[i];pp != NULLPING;pp = pp->next){
- printf("%-16s",inet_ntoa(pp->remote));
- printf("%8lu%8lu",pp->count,pp->echoes);
- printf("%4lu%10lu%10lu%8u\n",
- (long)pp->echoes * 100 / pp->count,
- pp->echoes != 0 ?
- TICK2MS(pp->ttotal) / pp->echoes : 0,
- TICK2SEC(pp->timer.start),pp->length);
- }
- }
- return 0;
- }
- if(strcmp(argv[1],"clear") == 0){
- for(i=0;i<PMOD;i++){
- for(pp = ping[i];pp != NULLPING;pp = pp1){
- pp1 = pp->next;
- del_ping(pp);
- }
- }
- return 0;
- }
- if(strcmp(argv[1],"length") == 0){
- if(argc < 3)
- printf("ping length %u\n",pinglen);
- else
- pinglen = atoi(argv[2]) % 4096;
- return 0;
- }
- if((dest = resolve(argv[1])) == 0){
- printf(badhost,argv[1]);
- return 1;
- }
- /* See if dest is already in table */
- hval = hash_ping(dest);
- for(pp = ping[hval]; pp != NULLPING; pp = pp->next){
- if(pp->remote == dest){
- break;
- }
- }
- if(argc > 2){
- /* Inter-ping time is specified; set up timer structure */
- if(pp == NULLPING)
- if ((pp = add_ping(dest)) == NULLPING){
- printf(nospace);
- return 1;
- }
- pp->timer.start = SEC2TICK(atol(argv[2]));
- pp->timer.func = ptimeout;
- pp->timer.arg = (char *)pp;
- pp->remote = dest;
- pp->length = (argc > 3)? (atoi(argv[3]) % 4096) : pinglen;
- start_timer(&pp->timer);
- pp->count++;
- pingem(dest,iclk,REPEAT,pp->length);
- } else
- pingem(dest,iclk,ONESHOT,pinglen);
-
- return 0;
- }
-
- /* Called by ping timeout */
- void
- ptimeout(p)
- char *p;
- {
- register struct ping *pp;
-
- /* Send another ping */
- pp = (struct ping *)p;
- pp->count++;
- pingem(pp->remote,iclk,REPEAT,pp->length);
- start_timer(&pp->timer);
- }
- /* Send ICMP Echo Request packet */
- static
- pingem(dest,seq,id,len)
- int32 dest;
- int16 seq;
- int16 id;
- int16 len;
- {
- struct mbuf *bp,*htonicmp();
- struct mbuf *dbp = NULLBUF;
- struct icmp icmp;
- int i;
- extern struct icmp_stats icmp_stats;
-
- if(len != 0){
- if((dbp = alloc_mbuf(len)) == NULLBUF){
- printf(nospace);
- return 0;
- }
- for(i = 1; i <= len; i++)
- dbp->data[i - 1] = uchar(i);
- dbp->cnt = len;
- }
- icmp_stats.output[ECHO_REQ]++;
- icmp.type = ECHO_REQ;
- icmp.code = 0;
- icmp.args.echo.seq = seq;
- icmp.args.echo.id = id;
- if((bp = htonicmp(&icmp,dbp)) == NULLBUF){
- free_p(dbp);
- return 0;
- }
- return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
- }
-
- /* Called with incoming Echo Reply packet */
- int
- echo_proc(source,dest,icmp)
- int32 source,dest;
- struct icmp *icmp;
- {
- register struct ping *pp;
- int16 hval,hash_ping();
- long rtt;
-
- if ((rtt = iclk - icmp->args.echo.seq) < 0)
- rtt += 65536L;
- hval = hash_ping(source);
- for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
- if(pp->remote == source)
- break;
- if(pp == NULLPING || icmp->args.echo.id != 1){
- printf("%s: echo reply id %u seq %u, %lu ms\n",
- inet_ntoa(source),
- icmp->args.echo.id,icmp->args.echo.seq,
- TICK2MS(rtt));
- fflush(stdout);
- } else {
- /* Repeated poll, just keep stats */
- pp->ttotal += rtt;
- pp->echoes++;
- }
- }
- static
- int16
- hash_ping(dest)
- int32 dest;
- {
- int16 hval;
-
- hval = (hiword(dest) ^ loword(dest)) % PMOD;
- return hval;
- }
- /* Add entry to ping table */
- static
- struct ping *
- add_ping(dest)
- int32 dest;
- {
- struct ping *pp;
- int16 hval,hash_ping();
-
- pp = (struct ping *)calloc(1,sizeof(struct ping));
- if(pp == NULLPING)
- return NULLPING;
-
- hval = hash_ping(dest);
- pp->prev = NULLPING;
- pp->next = ping[hval];
- if(pp->next != NULLPING)
- pp->next->prev = pp;
- ping[hval] = pp;
- return pp;
- }
- /* Delete entry from ping table */
- static
- del_ping(pp)
- struct ping *pp;
- {
- int16 hval,hash_ping();
-
- stop_timer(&pp->timer);
-
- if(pp->next != NULLPING)
- pp->next->prev = pp->prev;
- if(pp->prev != NULLPING) {
- pp->prev->next = pp->next;
- } else {
- hval = hash_ping(pp->remote);
- ping[hval] = pp->next;
- }
- free((char *)pp);
- }
- ə